package datastructure.linked;

import javax.swing.*;
import java.net.SocketTimeoutException;
import java.util.function.Consumer;

/**
 * 单向链表
 *
 * @author 杨 强
 * @package datastructure.linked
 * @createTime 2023-03-01 22:02
 */
public class SinglyLinkList {
    private Node head; // 头部节点

    /**
     * 往头部添加节点
     * @param value
     */
    public void addFirst(int value) {
        // 把添加节点作为头部节点, 然后下一个下一个节点指向以前的头部节点.
        this.head = new Node(value, this.head);
    }

    /**
     * while循环链表
     * 如果我们遍历的时候要对节点做事情的话,可以把做事情的行为用函数式接口传进来,比如Consumer函数式接口
     */
    public void whileLoop(){
        // 得到当前头节点
        Node head = this.head;
        // 头节点的下一个节点不为空就一直遍历
        while (head.next != null){
            // 做一些事.....
            System.out.println(head.value);
            head = head.next;
        }
        // 最后一个, 因为最后一个的下一个节点没有值
        System.out.println(head.value);
    }


    /**
     * for循环遍历
     * 如果我们遍历的时候要对节点做事情的话,可以把做事情的行为用函数式接口传进来,比如Consumer函数式接口
     */
    public void forLoop() {
        for (Node curr = this.head; curr != null; curr = curr.next) {
            // 做一些事
            System.out.println(curr.value);
        }
    }


    // 迭代器遍历省略......
    /*
        public class SinglyLinkedList implements Iterable<Integer> {
            // ...
            private class NodeIterator implements Iterator<Integer> {
                Node curr = head;

                public boolean hasNext() {
                    return curr != null;
                }

                public Integer next() {
                    int value = curr.value;
                    curr = curr.next;
                    return value;
                }
            }

            public Iterator<Integer> iterator() {
                return new NodeIterator();
            }
        }
     */


    /**
     * 递归遍历
     * @param before
     * @param after
     */
    public void recursionLoop(Consumer<Integer> before, Consumer<Integer> after){
        recursion(head, before, after);
    }

    /**
     * 编写递归函数,做的事就是遍历节点需要做的事情, 针对某个节点的操作
     * @param node 遍历的每个节点
     * @param before 遍历节点前做的操作
     * @param after 遍历节点后做的操作
     */
    private void recursion(Node node, Consumer<Integer> before, Consumer<Integer> after){
        // 当节点为空退出循环
        if (node == null){
            return;
        }
        before.accept(node.value);
        System.out.println(node.value);
        after.accept(node.value);

        // 继续递归
        recursion(node.next, before, after);
    }

}